Skip to content

Conversation

@bmuddha
Copy link
Contributor

@bmuddha bmuddha commented Nov 22, 2025

Summary by CodeRabbit

  • New Features

    • Support for batch RPC requests: multiple requests can be submitted together, processed concurrently, and returned as a single aggregated response.
  • Bug Fixes

    • Error responses now consistently include Access-Control headers.
  • Tests

    • Added end-to-end test coverage for batch RPC request handling.
  • Chores

    • Added reqwest dependency for HTTP client usage.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link

github-actions bot commented Nov 22, 2025

Manual Deploy Available

You can trigger a manual deploy of this PR branch to testnet:

Deploy to Testnet 🚀

Alternative: Comment /deploy on this PR to trigger deployment directly.

⚠️ Note: Manual deploy requires authorization. Only authorized users can trigger deployments.

Comment updated automatically when the PR is synchronized.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 22, 2025

📝 Walkthrough

Walkthrough

Added batch JSON-RPC support to the HTTP layer. Introduced RpcRequest enum with Single(JsonHttpRequest) and Multi(Vec<JsonHttpRequest>) variants and updated parse_body to return RpcRequest. The HTTP dispatcher now handles Multi by concurrently processing sub-requests with FuturesOrdered, aggregating individual responses into a single JSON array while preserving per-request IDs. Access-Control headers are applied to error responses and to the final response. A workspace dev-dependency on reqwest was added and a new integration test exercising batch requests was introduced.

Possibly related PRs

  • Rpc/execution related metrics #584: Touches the same server/http/dispatch.rs dispatch path and modifies request-processing instrumentation, overlapping code areas adjusted here.

Suggested reviewers

  • thlorenz
  • GabrielePicco
  • lucacillario
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bmuddha/feat/support-batch-requests

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1504937 and 90d0fee.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (2)
  • Cargo.toml (1 hunks)
  • magicblock-aperture/src/requests/http/mod.rs (3 hunks)
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579

Applied to files:

  • magicblock-aperture/src/requests/http/mod.rs
📚 Learning: 2025-11-20T08:57:07.217Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 650
File: magicblock-chainlink/src/submux/subscription_task.rs:13-99
Timestamp: 2025-11-20T08:57:07.217Z
Learning: In the magicblock-validator repository, avoid posting review comments that merely confirm code is correct or matches intended behavior without providing actionable feedback, suggestions for improvement, or identifying potential issues. Such confirmatory comments are considered unhelpful noise by the maintainers.

Applied to files:

  • magicblock-aperture/src/requests/http/mod.rs
📚 Learning: 2025-11-21T11:03:26.756Z
Learnt from: thlorenz
Repo: magicblock-labs/magicblock-validator PR: 664
File: magicblock-chainlink/src/testing/mod.rs:342-370
Timestamp: 2025-11-21T11:03:26.756Z
Learning: In the magicblock-validator codebase, avoid leaving review comments that merely acknowledge code is correct or well-structured when there is no actionable suggestion, improvement, or issue to flag. Only comment when there is something specific to recommend, fix, or clarify.

Applied to files:

  • magicblock-aperture/src/requests/http/mod.rs
📚 Learning: 2025-11-19T12:55:48.931Z
Learnt from: Dodecahedr0x
Repo: magicblock-labs/magicblock-validator PR: 639
File: test-integration/test-tools/src/validator.rs:193-197
Timestamp: 2025-11-19T12:55:48.931Z
Learning: In the magicblock-validator codebase, when constructing arguments for the light CLI test validator in start_light_validator_with_config (test-integration/test-tools/src/validator.rs), the shlex::split approach is necessary because the light CLI does not handle whitespaces properly in validator arguments. The string concatenation + shlex parsing pattern should not be refactored to direct argument construction in this specific case.

Applied to files:

  • magicblock-aperture/src/requests/http/mod.rs
📚 Learning: 2025-11-24T08:45:11.154Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 675
File: Cargo.toml:145-145
Timestamp: 2025-11-24T08:45:11.154Z
Learning: The reqwest dependency version 0.11 is intentionally used in the magicblock-validator project to maintain compatibility with the Solana client dependencies.

Applied to files:

  • Cargo.toml
🔇 Additional comments (3)
Cargo.toml (1)

145-145: Workspace dependency addition is appropriate.

The addition of reqwest = "0.11" is correct for the new HTTP client functionality in integration tests.

Based on learnings, version 0.11 is intentionally used to maintain compatibility with Solana client dependencies.

magicblock-aperture/src/requests/http/mod.rs (2)

23-23: LGTM!

The import change from JsonHttpRequest to RpcRequest correctly aligns with the new enum-based approach for handling both single and batch JSON-RPC requests.


48-65: LGTM!

The refactored parse_body function correctly:

  • Returns RpcRequest enum to support both single and batch requests
  • Handles leading whitespace with trim_ascii_start() before detection
  • Distinguishes between single ({) and batch (non-{) requests by inspecting the first byte
  • Delegates validation and deserialization to the JSON parser

The leading whitespace handling concern from previous reviews has been addressed.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0cc6810 and bf6aee5.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • Cargo.toml (1 hunks)
  • magicblock-aperture/Cargo.toml (1 hunks)
  • magicblock-aperture/src/requests/http/mod.rs (3 hunks)
  • magicblock-aperture/src/requests/mod.rs (1 hunks)
  • magicblock-aperture/src/server/http/dispatch.rs (4 hunks)
  • magicblock-aperture/tests/batches.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-21T14:00:54.642Z
Learnt from: bmuddha
Repo: magicblock-labs/magicblock-validator PR: 578
File: magicblock-aperture/src/requests/websocket/account_subscribe.rs:18-27
Timestamp: 2025-10-21T14:00:54.642Z
Learning: In magicblock-aperture account_subscribe handler (src/requests/websocket/account_subscribe.rs), the RpcAccountInfoConfig fields data_slice, commitment, and min_context_slot are currently ignored—only encoding is applied. This is tracked as technical debt in issue #579: https://github.com/magicblock-labs/magicblock-validator/issues/579

Applied to files:

  • magicblock-aperture/src/server/http/dispatch.rs
🧬 Code graph analysis (1)
magicblock-aperture/src/server/http/dispatch.rs (2)
magicblock-aperture/src/requests/payload.rs (3)
  • encode (61-79)
  • encode (105-115)
  • encode (120-133)
magicblock-aperture/src/requests/http/mod.rs (2)
  • extract_bytes (67-100)
  • parse_body (49-64)
🔇 Additional comments (2)
magicblock-aperture/Cargo.toml (1)

72-72: LGTM!

The addition of reqwest as a dev-dependency is appropriate for the new batch request tests in tests/batches.rs.

magicblock-aperture/src/server/http/dispatch.rs (1)

110-112: LGTM! Access control headers on error responses.

Good catch to ensure CORS headers are set on error responses. This prevents CORS-related failures in browser clients when requests fail.

Copy link
Collaborator

@thlorenz thlorenz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (with a note around error returns) + please consider removing that handrolled JSON generator (possibley run a quick test regarding perf).

}
.trim_ascii_start();
// Hacky/cheap way to detect single request vs an array of requests
if body_bytes.first().map(|&b| b == b'{').unwrap_or_default() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the user sends an invalid payload, i.e. "Hello world" (which is valid JSON).
At that point we'd already try to interpret as an array and the error message might be misleading.

Maybe we should also check specifically for [ and have a third branch which errors with a message that an array or object is expected.

I ran such an invalid request against our current implementation and it returns:

{
    "jsonrpc": "2.0",
    "error": {
        "code": -32700,
        "message": "error parsing request body: invalid type: string \"Hello World\", expected struct JsonRequest at line 1 column 13\n\n\tlo World\"\n\t........^\n"
    }
}

Running against stock solana validator returns:

{
    "jsonrpc": "2.0",
    "error": {
        "code": -32700,
        "message": "Parse error"
    },
    "id": null
}

So we already do a better job here it seems. I double checked that we still return the same message on this branch (while writing this comment), so it seems fine either way, just something to consider to make things more explicit.

let response = self.process(&mut request).await;
// Handle any errors from the execution stage
let response = unwrap!(response, Some(&request.id));
let (response, id) = match request {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we handrolling JSON generators? Why not use a proper crate to do this?
This code in the middle of request handling is quite verbose and confused me to the point where I thought this is a JSON parser actually.

We should use serde_json instead to build up a proper request and then serialize
Or we could use the json! macro.

If this is done for speed then we should be sure the difference is worth it.
serde_json does pretty much what your code is doing, just more battle tested and most likely pretty much as performant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's done for speed mostly yes, each handler returns a byte arrray of already serialized bodies, in order to use more expensive json serializer, we need to convert those bodies back to json structures and then serialize it back, which is 3 times more work than this implementation does.

Copy link
Collaborator

@GabrielePicco GabrielePicco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@bmuddha bmuddha merged commit b1aac74 into master Nov 25, 2025
18 checks passed
@bmuddha bmuddha deleted the bmuddha/feat/support-batch-requests branch November 25, 2025 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants